package com.bolt.common.utils;


import com.bolt.convention.data.ResultMessage;
import com.bolt.convention.data.Results;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.util.CollectionUtils;

import javax.validation.ConstraintViolation;
import javax.validation.ElementKind;
import javax.validation.Path;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * 验证工具类
 * 仅限模块内部使用，开发中请不要使用这个类

 */
public class ValidationUtil {

    public static List<ResultMessage.ViolationItem> convertToResultViolationItems(
            Set<? extends ConstraintViolation<?>> constraintViolations) {
        return convertToResultViolationItems(constraintViolations, null, null);
    }

    public static List<ResultMessage.ViolationItem> convertToResultViolationItems(
            Set<? extends ConstraintViolation<?>> constraintViolations,
            ParameterNameDiscoverer parameterNameDiscoverer,
            Method method) {
        if (CollectionUtils.isEmpty(constraintViolations)) {
            return null;
        }
        List<ResultMessage.ViolationItem> violationItems = new ArrayList<>(constraintViolations.size());
        for (ConstraintViolation constraintViolation : constraintViolations) {
            String fieldName = getFieldName(parameterNameDiscoverer, method, constraintViolation);
            violationItems.add(Results.buildViolationItem(fieldName, constraintViolation.getMessage()));
        }
        return violationItems;
    }

    private static String getFieldName(ParameterNameDiscoverer parameterNameDiscoverer,
                                       Method method, ConstraintViolation constraintViolation) {
        String fieldName = "";
        for (Path.Node node : constraintViolation.getPropertyPath()) {
            if (node.getKind() == ElementKind.PARAMETER) {
                fieldName = getParameterName(node, method, parameterNameDiscoverer);
            } else if (node.getKind() == ElementKind.PROPERTY) {
                fieldName = node.getName();
            } else if (node.getKind() == ElementKind.RETURN_VALUE) {
                fieldName = node.getName();
            }
        }
        return fieldName;
    }

    private static String getParameterName(Path.Node node, Method method,
                                           ParameterNameDiscoverer parameterNameDiscoverer) {
        if (parameterNameDiscoverer == null || method == null) {
            return node.getName();
        } else {
            int index = node.as(Path.ParameterNode.class).getParameterIndex();
//            if (method.getParameters()[index].isAnnotationPresent(Name.class)) {
//                return method.getParameters()[index].getAnnotation(Name.class).value();
//            }
            String[] names = parameterNameDiscoverer.getParameterNames(method);
            return names == null ? node.getName() : names[index];
        }
    }
}
